package com.ruoyi.business.controller;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.IdUtil;
import com.ruoyi.business.domain.Train;
import com.ruoyi.business.domain.dto.TrainCarriageGroupDTO;
import com.ruoyi.business.domain.vo.TrainCarriageVo;
import com.ruoyi.business.enums.SeatColEnum;
import com.ruoyi.business.service.ITrainService;
import com.ruoyi.common.utils.ServletUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.TrainCarriage;
import com.ruoyi.business.service.ITrainCarriageService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.util.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 火车车厢Controller
 * 
 * @author ruoyi
 * @date 2025-03-06
 */
@RestController
@RequestMapping("/base/train-carriage")
public class TrainCarriageController extends BaseController
{
    @Autowired
    private ITrainCarriageService trainCarriageService;

    @Autowired
    private ITrainService trainService;

    /**
     * 导出火车车厢列表
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:export')")
    @Log(title = "火车车厢", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TrainCarriage trainCarriage)
    {
        List<TrainCarriage> list = trainCarriageService.selectTrainCarriageList(trainCarriage);
        ExcelUtil<TrainCarriage> util = new ExcelUtil<TrainCarriage>(TrainCarriage.class);
        util.exportExcel(response, list, "火车车厢数据");
    }

    /**
     * 导入火车管理列表
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:add')")
    @Log(title = "火车车厢", businessType = BusinessType.IMPORT)
    @PostMapping("/importExcel")
    public AjaxResult importExcel(MultipartFile file) throws IOException {
        ExcelUtil<TrainCarriageVo> util = new ExcelUtil<TrainCarriageVo>(TrainCarriageVo.class);
        List<TrainCarriageVo> list = util.importExcel(file.getInputStream());

        // 成功和失败的列表
        List<TrainCarriage> successList = new ArrayList<>();
        List<Map<String, Object>> errorList = new ArrayList<>();

        // 获取所有有效车次编号
        List<Train> trainList = trainService.selectTrainList(new Train());
        Set<String> validTrainCodes = trainList.stream().map(Train::getCode).collect(Collectors.toSet());
        
        // 用于检查同一车次下厢号是否重复的Map
        Map<String, Set<Long>> trainIndexMap = new HashMap<>();

        // 首先检查导入数据
        for (TrainCarriageVo vo : list) {
            Map<String, Object> errorMap = new HashMap<>();
            boolean hasError = false;

            // 生成一个ID，便于追踪
            Long id = vo.getId();
            
            // 复制VO属性到错误Map（用于错误展示）
            errorMap.put("id", id);
            errorMap.put("trainCode", vo.getTrainCode());
            errorMap.put("index", vo.getIndex());
            errorMap.put("seatType", vo.getSeatType());
            errorMap.put("rowCount", vo.getRowCount());

            // 验证车次编号是否存在
            if (!validTrainCodes.contains(vo.getTrainCode())) {
                errorMap.put("errorMsg", "车次编号不存在");
                errorList.add(errorMap);
                continue;
            }
            
            // 检查同一车次下厢号是否重复（导入数据内）
            if (!trainIndexMap.containsKey(vo.getTrainCode())) {
                trainIndexMap.put(vo.getTrainCode(), new HashSet<>());
            }

            if (trainIndexMap.get(vo.getTrainCode()).contains(vo.getIndex())) {
                errorMap.put("errorMsg", "同一车次下厢号在导入数据中重复");
                errorList.add(errorMap);
                continue;
            }
            trainIndexMap.get(vo.getTrainCode()).add(vo.getIndex());

            // 由于Mapper的查询条件不完整，我们需要手动检查是否存在相同车次编号和厢号的组合
            // 查询所有指定车次的车厢
            TrainCarriage queryParam = new TrainCarriage();
            queryParam.setTrainCode(vo.getTrainCode());
            List<TrainCarriage> carriagesOfTrain = trainCarriageService.selectTrainCarriageList(queryParam);
            
            // 手动检查是否有相同厢号，并记录ID（如果存在）
            Optional<TrainCarriage> existingCarriage = carriagesOfTrain.stream()
                    .filter(carriage -> carriage.getIndex().equals(vo.getIndex()))
                    .findFirst();
            
            if (existingCarriage.isPresent()) {
                errorMap.put("errorMsg", "厢号已存在");
                errorMap.put("id", existingCarriage.get().getId()); // 记录现有数据的ID
                errorList.add(errorMap);
                continue;
            }

            // 根据座位类型设置固定列数
            Long colCount;
            switch (vo.getSeatType()) {
                case "1": // 一等座
                    colCount = 4L;
                    break;
                case "2": // 二等座
                    colCount = 5L;
                    break;
                case "3": // 商务座
                    colCount = 2L;
                    break;
                default:
                    errorMap.put("errorMsg", "座位类型无效或不支持");
                    errorList.add(errorMap);
                    continue;
            }

            // 创建TrainCarriage对象
            TrainCarriage trainCarriage = new TrainCarriage();
            trainCarriage.setId(id);
            trainCarriage.setTrainCode(vo.getTrainCode());
            trainCarriage.setIndex(vo.getIndex());
            trainCarriage.setSeatType(vo.getSeatType());
            trainCarriage.setRowCount(vo.getRowCount());
            trainCarriage.setColCount(colCount);

            // 计算座位数 = 排数 * 列数
            trainCarriage.setSeatCount(vo.getRowCount() * colCount);

            successList.add(trainCarriage);
        }

        // 如果有正确的数据，则导入
        int successCount = 0;
        if (!successList.isEmpty()) {
            successCount = trainCarriageService.insertTrainCarriages(successList);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("successCount", successCount);
        result.put("errorList", errorList);

        return AjaxResult.success("导入完成", result);
    }

    /**
     * 下载车站导入模板
     */
    @PreAuthorize("@ss.hasPermi('base:platform:export')")
    @Log(title = "火车车厢", businessType = BusinessType.EXPORT)
    @PostMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        // 使用自定义模板下载方法，不包含错误原因列
        trainCarriageService.downloadCustomTemplate(response);
    }

    /**
     * 获取火车车厢详细信息
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(trainCarriageService.selectTrainCarriageById(id));
    }

    /**
     * 新增火车车厢
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:add')")
    @Log(title = "火车车厢", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TrainCarriage trainCarriage)
    {
        trainCarriage.setId(IdUtil.getSnowflakeNextId());
        //自动计算
        List<SeatColEnum> colsByType = SeatColEnum.getColsByType(trainCarriage.getSeatType());
        trainCarriage.setColCount((long) colsByType.size());
        trainCarriage.setSeatCount(colsByType.size() * trainCarriage.getRowCount());
        return toAjax(trainCarriageService.insertTrainCarriage(trainCarriage));
    }

    /**
     * 修改火车车厢
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:edit')")
    @Log(title = "火车车厢", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TrainCarriage trainCarriage)
    {
        return toAjax(trainCarriageService.updateTrainCarriage(trainCarriage));
    }

    /**
     * 删除火车车厢
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:remove')")
    @Log(title = "火车车厢", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(trainCarriageService.deleteTrainCarriageByIds(ids));
    }

    @GetMapping("/list")
    @PreAuthorize("@ss.hasPermi('base:train-carriage:list')")
    public AjaxResult list(TrainCarriage trainCarriage) {
        startPage();
        List<TrainCarriage> list = trainCarriageService.selectTrainCarriageList(trainCarriage);
        TableDataInfo tableData = getDataTable(list);

        // 获取分组后数据
        List<TrainCarriageGroupDTO> groups = trainCarriageService.selectTrainCarriageGroups(trainCarriage);

        // 创建一个AjaxResult对象，它支持put方法
        AjaxResult result = AjaxResult.success();
        result.put("rows", tableData.getRows());
        result.put("total", tableData.getTotal());
        result.put("trainTotal", groups.size());

        return result;
    }

    @GetMapping("/trainGroups")
    @PreAuthorize("@ss.hasPermi('base:train-carriage:list')")
    public AjaxResult trainGroups(TrainCarriage trainCarriage) {
        List<TrainCarriageGroupDTO> groups = trainCarriageService.selectTrainCarriageGroups(trainCarriage);

        // 处理分页
        Integer pageNum = ServletUtils.getParameterToInt("pageNum", 1);
        Integer pageSize = ServletUtils.getParameterToInt("pageSize", 10);

        int total = groups.size();
        int fromIndex = (pageNum - 1) * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, total);

        List<TrainCarriageGroupDTO> pageGroups =
                (fromIndex < toIndex) ? groups.subList(fromIndex, toIndex) : new ArrayList<>();

        AjaxResult result = AjaxResult.success();
        result.put("rows", pageGroups);
        result.put("total", total);

        return result;
    }

    /**
     * 导出错误数据 - 保持与导入模板一致的列结构
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:export')")
    @Log(title = "火车车厢", businessType = BusinessType.EXPORT)
    @PostMapping("/exportErrorData")
    public void exportErrorData(HttpServletResponse response, @RequestParam(required = false) String errorData) throws IOException {
        if (StringUtils.hasText(errorData)) {
            try {
                // 解析错误数据JSON
                ObjectMapper mapper = new ObjectMapper();
                List<Map<String, Object>> dataList = mapper.readValue(errorData, 
                    mapper.getTypeFactory().constructCollectionType(List.class, Map.class));
                
                // 转换为TrainCarriageVo对象列表
                List<TrainCarriageVo> voList = new ArrayList<>();
                for (Map<String, Object> item : dataList) {
                    TrainCarriageVo vo = new TrainCarriageVo();
                    
                    // 设置ID
                    if (item.get("id") != null) {
                        try {
                            vo.setId(Long.parseLong(item.get("id").toString()));
                        } catch (NumberFormatException e) {
                            vo.setId(0L);
                        }
                    }
                    
                    vo.setTrainCode(item.get("trainCode") != null ? item.get("trainCode").toString() : "");
                    
                    // 处理索引
                    if (item.get("index") != null) {
                        try {
                            vo.setIndex(Long.parseLong(item.get("index").toString()));
                        } catch (NumberFormatException e) {
                            vo.setIndex(0L);
                        }
                    } else {
                        vo.setIndex(0L);
                    }
                    
                    // 座位类型
                    vo.setSeatType(item.get("seatType") != null ? item.get("seatType").toString() : "1");
                    
                    // 处理排数
                    if (item.get("rowCount") != null) {
                        try {
                            vo.setRowCount(Long.parseLong(item.get("rowCount").toString()));
                        } catch (NumberFormatException e) {
                            vo.setRowCount(0L);
                        }
                    } else {
                        vo.setRowCount(0L);
                    }
                    
                    // 添加错误原因
                    vo.setErrorMsg(item.get("errorMsg") != null ? item.get("errorMsg").toString() : "数据验证失败");
                    
                    // 根据座位类型设置固定列数和座位数
                    Long colCount;
                    switch (vo.getSeatType()) {
                        case "1": // 一等座
                            colCount = 4L;
                            break;
                        case "2": // 二等座
                            colCount = 5L;
                            break;
                        case "3": // 商务座
                            colCount = 2L;
                            break;
                        default:
                            colCount = 4L;
                    }
                    vo.setColCount(colCount);
                    vo.setSeatCount(vo.getRowCount() * colCount);
                    
                    voList.add(vo);
                }
                
                // 使用ExcelUtil导出
                ExcelUtil<TrainCarriageVo> util = new ExcelUtil<>(TrainCarriageVo.class);
                util.exportExcel(response, voList, "火车车厢错误数据");
            } catch (Exception e) {
                logger.error("处理数据失败", e);
                // 导出失败时返回空数据
                ExcelUtil<TrainCarriageVo> util = new ExcelUtil<>(TrainCarriageVo.class);
                util.exportExcel(response, new ArrayList<>(), "火车车厢错误数据");
            }
        } else {
            // 没有错误数据时导出空表
            ExcelUtil<TrainCarriageVo> util = new ExcelUtil<>(TrainCarriageVo.class);
            util.exportExcel(response, new ArrayList<>(), "火车车厢错误数据");
        }
    }

    /**
     * 清空火车车厢数据
     */
    @PreAuthorize("@ss.hasPermi('base:train-carriage:remove')")
    @Log(title = "火车车厢", businessType = BusinessType.CLEAN)
    @PostMapping("/clear")
    public AjaxResult clear(@RequestBody Map<String, String> passwordMap) {
        String password = passwordMap.get("password");
        System.out.println("密码：" + password);
        if (!"admin123".equals(password)) {
            return AjaxResult.error("密码错误");
        }
        return toAjax(trainCarriageService.clearTrainCarriage());
    }
}
